package cn.demoncat.util.io;

import cloud.tianai.captcha.template.slider.DefaultSliderCaptchaTemplate;
import cloud.tianai.captcha.template.slider.SliderCaptchaInfo;
import cloud.tianai.captcha.template.slider.SliderCaptchaTemplate;
import cn.demoncat.util.exception.IoRuntimeException;
import cn.demoncat.util.io.config.SliderProperties;
import cn.demoncat.util.lang.StringUtil;
import cn.demoncat.util.lang.constant.StringConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;

import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 滑块验证码
 *
 * 背景图片：限制600*300；默认/resources/slider/bg/*，可以通过 slider.url 配置（多个用,分隔）
 * 滑块图片：限制100*100；默认/resources/slider/drag/*
 *
 * @author 延晓磊
 * @since 2021年07月01日
 */
@Component
public class SliderUtil {


    // 滑块模板
    private final SliderCaptchaTemplate template;


    @Autowired
    public SliderUtil(SliderProperties sliderProperties) {
        // 滑块模板
        template = new DefaultSliderCaptchaTemplate(false);
        // 配置滑块图片（任意数量，随机抽取；限制100*100）
        Map<String, URL> map = new HashMap<>(3);
        map.put(DefaultSliderCaptchaTemplate.ACTIVE_IMAGE_NAME, getLocalUrl("slider/drag/1/active.png"));
        map.put(DefaultSliderCaptchaTemplate.FIXED_IMAGE_NAME, getLocalUrl("slider/drag/1/fixed.png"));
        map.put(DefaultSliderCaptchaTemplate.MATRIX_IMAGE_NAME, getLocalUrl("slider/drag/1/matrix.png"));
        template.addTemplate(map);
        map = new HashMap<>(3);
        map.put(DefaultSliderCaptchaTemplate.ACTIVE_IMAGE_NAME, getLocalUrl("slider/drag/2/active.png"));
        map.put(DefaultSliderCaptchaTemplate.FIXED_IMAGE_NAME, getLocalUrl("slider/drag/2/fixed.png"));
        map.put(DefaultSliderCaptchaTemplate.MATRIX_IMAGE_NAME, getLocalUrl("slider/drag/2/matrix.png"));
        template.addTemplate(map);
        // 配置背景图片（任意数量，随机抽取；限制600*300）
        List<URL> urls = new ArrayList<>();
        if (StringUtil.isBlank(sliderProperties.getUrl())) {
            // 默认图片
            urls.add(getLocalUrl("slider/bg/1.jpg"));
            urls.add(getLocalUrl("slider/bg/2.jpg"));
        }else{
            // 自定义图片
            for (String url: sliderProperties.getUrl().split(",")) {
                urls.add(getUrl(url));
            }
        }
        template.setResource(urls);
    }

    /**
     * 生成滑块图片
     *
     * @return {xPercent:X轴百分比（校验参数），backgroundImage:背景图， sliderImage:移动图}
     *
     * @author 延晓磊
     * @since 2021年07月01日
     */
    public SliderCaptchaInfo get(){
        return template.getSlideImageInfo();
    }

    /**
     * 校验滑块
     *
     * @param newPercentage    用户输入的百分比
     * @param oriPercentage    原百分比
     *
     * @return
     *
     * @author 延晓磊
     * @since 2021年07月01日
     */
    public static boolean check(Float newPercentage, Float oriPercentage){
        if (newPercentage == null || Float.isNaN(newPercentage) || Float.isInfinite(newPercentage)
                || oriPercentage == null || Float.isNaN(oriPercentage) || Float.isInfinite(oriPercentage)) {
            return false;
        }
        // 容错值
        float tolerant = 0.02f;
        // 比较
        float maxTolerant = oriPercentage + tolerant;
        float minTolerant = oriPercentage - tolerant;
        return newPercentage >= minTolerant && newPercentage <= maxTolerant;
    }



    /**
     * 获取URL
     *
     * @param url
     * @return
     */
    private static URL getUrl(String url){
        try {
            return new URL(url);
        } catch (MalformedURLException e) {
            throw new IoRuntimeException("读取滑块图片失败：" + url, e);
        }
    }

    /**
     * 获取本地URL
     *
     * @param url
     * @return
     */
    private static URL getLocalUrl(String url){
        try {
            return ResourceUtils.getURL(StringConstant.CLASSPATH + url);
        } catch (FileNotFoundException e) {
            throw new IoRuntimeException("读取滑块图片失败：" + url, e);
        }
    }
}
